--- 模块功能：MQTT客户端数据接收处理
-- @author openLuat
-- @module mqtt.mqttInMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28
module(..., package.seeall)

require "earthquakeWaring"
require "earthquakeWaringDril"
require "eqtParaNvm"
require "sendDeviceLocation"
require "remoteTextBroadcast"
require "getDevStatus"
require "logGenerator"
require "nvm"
require "logUploadHttp"
require "delGeneratorFlie"
require "networkTiming"
require "versionUpgrade"
require "registerTask"
require "deviceRestart"
require "deviceOnlineCheck"

--参数配置文件初始化
nvm.init("config.lua", true)
--变量初始化
local clientNo, typeId, orgId, slen, errInfo, logInfo, sysTime, action, acountSuspend =
nvm.get("info")[1], nvm.get("info")[3], tonumber(nvm.get("info")[4]), string.len, "", "",
    "", false, 0

-- 预警演练设备身份判别
local function containClientsOrNot(equipment_clients)
    local containResult = false
    log.info("#equipment_clients", #equipment_clients)
    for i = 1, #equipment_clients do
        log.info("equipment_clients", equipment_clients[i], "clientNo", clientNo)
        if equipment_clients[i] == clientNo then
            containResult = true
        end
    end
    return containResult
end

--主题是否包含判断
local function isContainTopic(topic)
    local containTopic = false
    local topicList = {}
    local centerNameList = string.split(nvm.get("centerName"), ",")
    for i = 1, #centerNameList, 1 do
        topicList[i] = "quake/" .. centerNameList[i]
        if topicList[i] == topic then containTopic = true end
    end
    return containTopic
end

--- MQTT客户端数据接收处理
-- @param mqttClient，MQTT客户端对象
-- @return 处理成功返回true，处理出错返回false
-- @usage mqttInMsg.proc(mqttClient)
function proc(mqttClient)
    local result, data, receiveMsg, base64DecodeMsg, aesDecryptMsg
    while true do
        sysTime = string.format("%04d-%02d-%02d %02d:%02d:%02d", os.date("*t").year,
            os.date("*t").month, os.date("*t").day, os.date("*t").hour, os.date("*t").min, os.date("*t").sec)
        result, data = mqttClient:receive(60000, "APP_SOCKET_SEND_DATA")
        errInfo = ""
        -- 接收到数据
        if result then
            receiveMsg = data.payload
            base64DecodeMsg = crypto.base64_decode(receiveMsg, slen(receiveMsg))
            aesDecryptMsg = crypto.aes_decrypt("ECB", "PKCS5", base64DecodeMsg,
                "keson-123abcdefg")
            local tjsondata, resultMqtt, errinfo = json.decode(aesDecryptMsg)
            local clientsBool, todo, exercise, msgCode, unitId = false
            log.info("mqtt payload", aesDecryptMsg)
            log.info("data.topic", data.topic)
            if data.topic == "action/" .. typeId then
                if resultMqtt and type(tjsondata) == "table" then
                    todo = tjsondata["todo"]
                    if tjsondata["clients"] then
                        clientsBool = containClientsOrNot(tjsondata["clients"])
                    end
                    
                    if todo == "exercise" then
                        if clientsBool then
                            earthquakeWaringDril.EarthquakeWarningDrillSystem(tjsondata)
                        else
                            errInfo = errInfo .. "[" .. sysTime .. "]" .. "[设备号限制:]" .. "设备身份判别结果:"
                                ..
                                tostring(clientsBool) .. "\n"
                        end
                    elseif todo == "setConfig" then --存储远程修改的设备参数
                        if clientsBool then
                            eqtParaNvm.saveParameters(tjsondata)
                        end
                    elseif todo == "readConfig" then --获取本地参数并上传到后端管理系统
                        eqtParaNvm.equipmentParametersRead(tjsondata)
                    elseif todo == "gps" then --上传设备位置
                        if clientsBool then
                            sendDeviceLocation.seviceLocationSendTask(tjsondata)
                        end
                    elseif todo == "devStatus" then --获取设备状态
                        if clientsBool then
                            getDevStatus.getAndSaveDevStatus()
                        end
                    elseif todo == "broadcast" then --远程文本播报
                        if clientsBool then
                            remoteTextBroadcast.broadcastRemoteTextTask(tjsondata)
                        end
                    elseif todo == "fetchAllLog" then --上传日志
                        if clientsBool then
                            logUploadHttp.uploadLogTask(tjsondata)
                        end
                    elseif todo == "clearAllLog" then --清除设备存储的所有日志文件
                        if clientsBool then
                            delGeneratorFlie.delAllExpiredFiles(tjsondata)
                        end
                    elseif todo == "synTime" then
                        if clientsBool then
                            networkTiming.setNetworkTimingByManual(tjsondata)
                        end
                    elseif todo == "update" then
                        if clientsBool then
                            versionUpgrade.deviceRestartUpgrade(tjsondata)
                        end
                    elseif todo == "register" then
                        if clientsBool then
                            registerTask.RegistrationServiceTask()
                        end
                    elseif todo == "altertinfo" then
                        if clientsBool then
                            registerTask.ChangeRegistrationInfoServiceTask()
                        end
                    elseif todo == "suspend" then
                        if clientsBool then
                            acountSuspend = acountSuspend + 1
                            if acountSuspend % 2 == 0 then
                                action = false
                            else
                                action = true
                            end
                            registerTask.PauseResumeServiceTask(action)
                        end
                    elseif todo == "authorize" then
                        if clientsBool then
                            registerTask.AuthorizationApplicationUpdateServiceTask()
                        end
                    elseif todo == "cancelAuth" then
                        if clientsBool then
                            registerTask.AuthorizationRevocationServiceTask()
                        end
                    elseif todo == "getTokenInfo" then
                        if clientsBool then
                            registerTask.AuthorizationQueryServiceTask()
                        end
                    elseif todo == "reboot" then
                        if clientsBool then
                            deviceRestart.restartDevice()
                        end
                    elseif todo == "status" then
                        deviceOnlineCheck.checkDeviceOnline()
                    end
                else
                    errInfo = errInfo .. "[" .. sysTime .. "]" .. "[json.decode error:]" .. errinfo .. "\n"
                    print("json.decode error", errinfo)
                end
            elseif isContainTopic(data.topic) then
                if resultMqtt and type(tjsondata) == "table" then
                    todo, exercise, msgCode = tjsondata["todo"], tjsondata["exercise"], tjsondata["2"]
                    log.info("msgCode", msgCode)
                    if exercise then --预警演练（云）
                        unitId = tonumber(tjsondata["13"])
                        if unitId == orgId then
                            earthquakeWaringDril.EarthquakeWarningDrillSystem(tjsondata)
                        end
                    elseif msgCode == "0199" then --单位预警取消（包含演习及模拟）
                        unitId = tonumber(tjsondata["17"])
                        if unitId == orgId then
                            earthquakeWaringDril.EarthquakeWarningDrillSystem(tjsondata)
                            earthquakeWaring.EarthquakeWarning(aesDecryptMsg, tjsondata, data.topic)
                        else
                            errInfo = errInfo .. "[" .. sysTime .. "]" .. "[错误信息:]所属部门ID不相符！\n"
                        end
                    elseif msgCode == "0201" or msgCode == "0202" then --模拟地震预警（本地）
                        unitId = tonumber(tjsondata["17"])
                        log.info("MQTT-EARTHQUAKE")
                        if unitId == orgId then
                            earthquakeWaring.EarthquakeWarning(aesDecryptMsg, tjsondata, data.topic)
                        end
                    elseif msgCode == "0101" or msgCode == "0102" then
                        earthquakeWaring.EarthquakeWarning(aesDecryptMsg, tjsondata, data.topic)
                    end
                end
            else
                errInfo = errInfo .. "[" .. sysTime .. "]" .. "[订阅主题满足要求:]" ..
                    "接收的主题:" .. data.topic .. "\n"
                logGenerator.generateLogTask(errInfo, "log")
            end
        else
            break
        end
    end
    log.info("MQTT TASK RESULT",result,"MQTT TASK DATA",data)
    return result or data == "timeout" or data == "APP_SOCKET_SEND_DATA"
end
